
#include "segment.h"
#include "locale.h"

Segment::Segment()
{
	const char * file = "data/dict.dat";
	const char * rmmFile = "data/reverse_dict.dat";

	dict = new Dictionary(rmmFile,Dictionary::RMM);
	
	patArray = new PatArray(dict);

	head = new Sentence();
	head->next = 0;
	tail = head;

	document = 0;
}


Segment::~Segment()
{
	delete dict;
	for(Sentence * cur = head->next; cur != 0;)
	{
		cur->free();
		Sentence * next = cur->next;
		delete cur;
		cur = next;
	}
}

//void Segment::split(wchar_t *sentence)
//{
//	int base = Trie::BASE_POS;
//	int next_base = -1;
//
//
//	wchar_t *begin = sentence;
//	wchar_t *end = begin;
//	wchar_t *last_pos;
//
//	while(*end != 0)
//	{
//		next_base = dict->forward(base,*end);
//		if( dict->is_phrase(next_base))
//		{
//			last_pos = end+1;   // 
//		}
//		else
//		{
//			if( begin==end)
//				last_pos = end +1;
//		}
//
//		if( next_base != -1)
//		{
//			base = next_base;
//			++end;
//		}else
//		{
//			output_result(begin,last_pos);
//			base = Trie::BASE_POS;
//			begin = last_pos;
//			end=begin;
//		}
//		
//	}
//
//	if(last_pos >begin)
//	{
//		output_result(begin,last_pos);
//	}
//	if(last_pos<end)
//	{
//		output_result(last_pos,end);
//	}
//}

void Segment::segmentSentences()
{
	for(Sentence* cur = head->next; cur != 0; cur = cur->next)
	{
		if(cur->needSeg)
		{
			segmentSentence(cur);
		}
	}
}

// segment sentence in RMM manner with RMM-dictionary
void Segment::segmentSentence(Sentence * se)
{
	int base = Trie::BASE_POS;
	int next_base = -1;


	wchar_t *begin = se->se + se->length;
	wchar_t *end = begin;
	wchar_t *last_pos;

	while(*end != 0)
	{
		next_base = dict->forward(base,*end);
		if( dict->is_phrase(next_base))
		{
			last_pos = end-1;   // 
		}
		else
		{
			if( begin==end)
				last_pos = end - 1;
		}

		if( next_base != -1)
		{
			base = next_base;
			--end;
		}else
		{
			se->insertWordBeginEnd(last_pos+1,begin);

			base = Trie::BASE_POS;
			begin = last_pos;
			end=begin;
		}
		
	}

	if(last_pos < begin)
	{
		se->insertWordBeginEnd(last_pos+1,begin);
	}
	if(last_pos > end)
	{
		se->insertWordBeginEnd(end+1,last_pos);
	}
}


void Segment::analysisDocument(wchar_t * wdocument)
{
	this->document = wdocument;

	splitIntoSentences();

//	segmentSentences();
	
	//add to pat array
	for(Sentence* cur = head->next; cur != 0; cur = cur->next)
	{
		if(cur->needSeg)
		{
			patArray->add(cur);
		}
	}
	patArray->generateNewWord();
}
bool Segment::analysisFile(const char * path)
{
	FILE * pFile = fopen(path,"r");
	
	if (pFile==NULL) 
	{
		printf("Error opening file.\n");
		return false;
	}
	long size=0;

	//even the file is empty, it'll return 1.
	while(!feof(pFile))
	{
		fgetc(pFile);
		++size;
	}

	rewind(pFile);
	char * buffer = new char[size];
	buffer[size-1] = 0;
	fread(buffer,sizeof(char),size-1,pFile);
	fclose(pFile);

	int wchar_size = CalculateCharToWchar(buffer,-1);
	wchar_t * wbuffer = new wchar_t[wchar_size];
	CharToWchar(buffer,wbuffer,wchar_size-1);
	wbuffer[wchar_size-1] = 0;
	
	delete [] buffer;

	this->analysisDocument(wbuffer);
	
	return true;
}

void Segment::info()
{
//	patArray->printContext();
//	patArray->printPrefixList();
//	patArray->printBoundaryCounterInfo();
//	patArray->printLcpData();
	patArray->printEntropyInOrder();	
}


void Segment::output_result(wchar_t * begin, wchar_t *end)
{	
	int size = CalculateWcharToChar(begin,end-begin);
	char * ansi_string = new char[size + 1];
	ansi_string[size] = 0;
	WcharToChar(begin,ansi_string,size+1);
	printf("%s/",ansi_string);
	delete [] ansi_string;
}

void Segment::output_result_reverse(wchar_t * begin, wchar_t *end)
{
	int size = CalculateWcharToChar(begin+1, end - begin);
	char * ansi_string = new char[size+1];
	ansi_string[size] = 0;
	WcharToChar(begin+1,ansi_string,size+1);
	printf("%s/ ", ansi_string);

	delete [] ansi_string;
}

void Segment::splitIntoSentences()
{
	wchar_t *begin=document;
	wchar_t *end=begin;
	

	
	bool curType=isChinese(end++);
	for(; *end != 0; ++end)
	{
		if(curType !=isChinese(end))
		{
			int size = end-begin;
			wchar_t * newSen;
			if(curType)
			{
				//create a new wchar string being and end with 0.
				newSen = new wchar_t[size+2];
				newSen[0] = newSen[size+1]=0;
				wcsncpy(newSen+1,begin,size);
			}
			else
			{
				newSen = new wchar_t[size+1];
				newSen[size] = 0;
				wcsncpy(newSen,begin,size);
			}
			addSentence(newSen, curType,size); 			
			curType = !curType;
			begin = end;
		}				
	}

	int size = end-begin;
	wchar_t * newSen;
	if(curType)
	{
		//create a new wchar string being and end with 0.
		newSen = new wchar_t[size+2];
		newSen[0] = newSen[size+1]=0;
		wcsncpy(newSen+1,begin,size);
	}
	else
	{
		newSen = new wchar_t[size+1];
		newSen[size] = 0;
		wcsncpy(newSen,begin,size);
	}
	addSentence(newSen, curType,size); 	
}

void Segment::addSentence(wchar_t *senten, bool needSeg, int senLen)
{

	Sentence * s = new Sentence();
	s->needSeg = needSeg;
	s->se = senten;
	s->length = senLen;
	s->next = 0;

	tail->next = s;
	tail = s;	
	
	if(head->next == 0)
	{
		head->next = s;
	}
}


//----------------------------------------------------------

bool isChinese(wchar_t* t)
{
	return *t>=0x4e00 && *t<=0x9FA0;
}




		